/*
 * Copyright 2011 Philippe Blanc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package me.l1k3.fx.client.channel;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style;

import me.l1k3.core.client.Core;
import me.l1k3.fx.client.channel.impl.ClipChannelImplJS;
import me.l1k3.fx.client.channel.inter.ChannelContext;
import me.l1k3.fx.client.channel.inter.ChannelDimension;
import me.l1k3.fx.client.channel.inter.DimensionConstant;
import me.l1k3.fx.client.channel.provider.DimensionProvider;
import me.l1k3.fx.client.channel.provider.DimensionProviderBlock;
import me.l1k3.fx.client.engine.inter.FXEngine;

public abstract class ClipChannel implements ChannelDimension {
    protected boolean backward;
    private DimensionProvider provider;
    protected DimensionConstant.Direction Direction;
    protected DimensionConstant.AnchorHorizontal AnchorHorizontal;
    protected DimensionConstant.AnchorVertical AnchorVertical;
    
    //- - - factory
    
    public final static ClipChannel create(String type) {
        if (type.equals(FXEngine.JS)) {
            return new ClipChannelImplJS();
        }
        
        return GWT.create(ClipChannel.class);
    }
    
    public final static ClipChannel box(String type) {
        return clip(type, DimensionConstant.Direction.BOTH, DimensionConstant.AnchorHorizontal.CENTER, DimensionConstant.AnchorVertical.CENTER);
    }
    
    public final static ClipChannel vertical(String type) {
        return clip(type, DimensionConstant.Direction.VERTICAL, DimensionConstant.AnchorHorizontal.CENTER, DimensionConstant.AnchorVertical.TOP);
    }
    
    public final static ClipChannel horizontal(String type) {
        return clip(type, DimensionConstant.Direction.HORIZONTAL, DimensionConstant.AnchorHorizontal.LEFT, DimensionConstant.AnchorVertical.CENTER);
    }
    
    public final static ClipChannel clip(String type, DimensionConstant.Direction Direction, DimensionConstant.AnchorHorizontal AnchorHorizontal, DimensionConstant.AnchorVertical AnchorVertical) {
        ClipChannel clip = create(type);
        clip.set(Direction, AnchorHorizontal, AnchorVertical);
        
        return clip;
    }
    
    //- - -
    
    public void setDimensionProvider(DimensionProvider provider) {
        this.provider = provider;
    }
    
    //- - -
    
    public void set(DimensionConstant.Direction Direction, DimensionConstant.AnchorHorizontal AnchorHorizontal, DimensionConstant.AnchorVertical AnchorVertical) {
        this.Direction = Direction;
        this.AnchorHorizontal = AnchorHorizontal;
        this.AnchorVertical = AnchorVertical;
    }
    
    protected final void setClip(ChannelContext context) {
        setClip(context.getStyle(), backward);
        context.setVisible(!backward);
    }
    
    protected final void setClip(Style style, boolean backward) {
        if(backward) {
            int width = getWidth();
            int height = getHeight();
            
            int top = 0;
            int right = width;
            int bottom = height;
            int left = 0;
            
            if(Direction==DimensionConstant.Direction.HORIZONTAL || Direction==DimensionConstant.Direction.BOTH) {

                switch(AnchorHorizontal) {
                    case LEFT:
                        left = right = 0;
                    break;
                    case CENTER:
                        left = right = width/2;
                    break;
                    case RIGHT:
                        left = right = width;
                    break;
                }
            }
            
            if(Direction==DimensionConstant.Direction.VERTICAL || Direction==DimensionConstant.Direction.BOTH) {
                
                switch(AnchorVertical) {
                    case TOP:
                        top = bottom = 0;
                    break;
                    case CENTER:
                        top = bottom = height/2;
                    break;
                    case BOTTOM:
                        top = bottom = height;
                    break;
                }
            }
                   
            style.setProperty("clip", "rect("+top+"px "+right+"px "+bottom+"px "+left+"px)");
        }
        else {
            style.setProperty("clip", "rect("+0+"px "+getWidth()+"px "+getHeight()+"px "+0+"px)");
            //style.setProperty("clip", "auto");
        }
    }
  
    protected int getWidth() {
        return provider.getWidth();
    }
    
    protected int getHeight() {
        return provider.getHeight();
    }
    
    //- - -
    
    @Override
    public final boolean isForward() {
        return !backward;
    }
    
    @Override
    public void init(ChannelContext context) {
        context.getStyle().setProperty("position", "absolute");
        
        backward = (Core.getComputedStyleProperty(context.getElement(), "visibility").equals("hidden") || Core.getComputedStyleProperty(context.getElement(), "display").equals("none"));
        
        if(provider==null) {
            provider = new DimensionProviderBlock(context.getElement());
        }
        
        context.enableShowAndHide();
        
        setClip(context);
    }

    @Override
    public void toggle(ChannelContext context) {
        backward = !backward;
        setClip(context);
    }
    
    /*
    @Override
    public void start(ChannelContext context) { }
    */
    
    /*
    @Override
    public void update(ChannelContext context) { }
    */   

    @Override
    public void complete(ChannelContext context) {
        toggle(context);
    }
}
